Thailand Trade dependency
Trade dependency play an important role of country’s economic development and stability, since it is vulnerable to external shocks such as economic recessions in trading partners, volatile global commodty prices, and disruptions in supply chains, potentially leading to job losses, price fluctuations, and instability, if the country relies heavily on a narrow ranges of exports and import sources. Thailand is export-dependence country for a long time. In this analysis, I will deep dive into Thailand trade dependency compared to other countries.
# Install package and call library 'WDI' and Import data
if (!require("WDI")) install.packages("WDI")
## Loading required package: WDI
if (!require("ggplot2")) install.packages("ggplot2")
## Loading required package: ggplot2
if (!require("dplyr")) install.packages("dplyr")
## Loading required package: dplyr
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
if (!require("tidyverse")) install.packages("tidyverse")
## Loading required package: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ lubridate 1.9.4 ✔ tibble 3.2.1
## ✔ purrr 1.0.2 ✔ tidyr 1.3.1
## ✔ readr 2.1.5
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
if (!require("rnaturalearth")) install.packages("rnaturalearthdata")
## Loading required package: rnaturalearth
if (!require("sf")) install.packages("sf")
## Loading required package: sf
## Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(tidyverse)
library(plotly)
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(WDI)
library(ggplot2)
library(dplyr)
library(rnaturalearth) # World Map Data from Natural Earth
library(sf) # Geographic Simple Features in R
library(forcats)
# import trade data
trade_data <- WDI(indicator=c("NY.GDP.PCAP.KD","NE.TRD.GNFS.ZS","NY.GDP.MKTP.KD","NE.EXP.GNFS.KD","NE.IMP.GNFS.KD"),extra=TRUE)
# chnage name into the easy name
names(trade_data)[names(trade_data)=='NY.GDP.PCAP.KD'] <- 'gdp_percap'
names(trade_data)[names(trade_data)=='NE.TRD.GNFS.ZS'] <- 'trade_dep'
names(trade_data)[names(trade_data)=='NY.GDP.MKTP.KD'] <- 'gdp'
names(trade_data)[names(trade_data)=='NE.EXP.GNFS.KD'] <- 'export'
names(trade_data)[names(trade_data)=='NE.IMP.GNFS.KD'] <- 'import'
trade_data <- trade_data %>%
mutate(net_trade_balance = export - import) # Compute net trade balance
#check heading and summarize of the data
head(trade_data)
## country iso2c iso3c year status lastupdated gdp_percap trade_dep gdp
## 1 Afghanistan AF AFG 1961 2025-01-28 NA NA NA
## 2 Afghanistan AF AFG 1974 2025-01-28 NA NA NA
## 3 Afghanistan AF AFG 1962 2025-01-28 NA NA NA
## 4 Afghanistan AF AFG 1963 2025-01-28 NA NA NA
## 5 Afghanistan AF AFG 1973 2025-01-28 NA NA NA
## 6 Afghanistan AF AFG 1989 2025-01-28 NA NA NA
## export import region capital longitude latitude income lending
## 1 NA NA South Asia Kabul 69.1761 34.5228 Low income IDA
## 2 NA NA South Asia Kabul 69.1761 34.5228 Low income IDA
## 3 NA NA South Asia Kabul 69.1761 34.5228 Low income IDA
## 4 NA NA South Asia Kabul 69.1761 34.5228 Low income IDA
## 5 NA NA South Asia Kabul 69.1761 34.5228 Low income IDA
## 6 NA NA South Asia Kabul 69.1761 34.5228 Low income IDA
## net_trade_balance
## 1 NA
## 2 NA
## 3 NA
## 4 NA
## 5 NA
## 6 NA
summary(trade_data)
## country iso2c iso3c year
## Length:17024 Length:17024 Length:17024 Min. :1960
## Class :character Class :character Class :character 1st Qu.:1976
## Mode :character Mode :character Mode :character Median :1992
## Mean :1992
## 3rd Qu.:2007
## Max. :2023
##
## status lastupdated gdp_percap trade_dep
## Length:17024 Length:17024 Min. : 0 Min. : 0.021
## Class :character Class :character 1st Qu.: 1299 1st Qu.: 41.587
## Mode :character Mode :character Median : 3679 Median : 60.544
## Mean : 11205 Mean : 72.403
## 3rd Qu.: 13066 3rd Qu.: 90.776
## Max. :224582 Max. :863.195
## NA's :3016 NA's :6106
## gdp export import region
## Min. :1.249e+03 Min. :4.651e+05 Min. :1.156e+06 Length:17024
## 1st Qu.:5.244e+09 1st Qu.:2.888e+09 1st Qu.:3.699e+09 Class :character
## Median :3.441e+10 Median :1.680e+10 Median :1.801e+10 Mode :character
## Mean :1.526e+12 Mean :4.019e+11 Mean :4.140e+11
## 3rd Qu.:3.624e+11 3rd Qu.:1.431e+11 3rd Qu.:1.488e+11
## Max. :9.335e+13 Max. :2.619e+13 Max. :2.615e+13
## NA's :3021 NA's :8456 NA's :8431
## capital longitude latitude income
## Length:17024 Length:17024 Length:17024 Length:17024
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## lending net_trade_balance
## Length:17024 Min. :-1.186e+12
## Class :character 1st Qu.:-3.611e+09
## Mode :character Median :-2.990e+08
## Mean : 4.319e+06
## 3rd Qu.: 3.107e+09
## Max. : 7.907e+11
## NA's :8471
# Filter data for 2023 and compute the variables
trade_data_2023 <- trade_data %>%
filter(year == 2023) %>%
mutate(
log_gdp_percap = log(gdp_percap),
net_trade_balance = log(abs(export - import)) * sign(export - import)
)
# Create the interactive Plotly plot
fig <- plot_ly(
data = trade_data_2023,
x = ~log_gdp_percap,
y = ~trade_dep,
type = 'scatter',
mode = 'markers+text',
text = ~iso3c,
textposition = 'top center',
marker = list(
opacity = 0.5,
color = ~net_trade_balance,
coloraxis = "coloraxis"
)
) %>%
layout(
title = "Trade Dependency and GDP Per Capita, 2023",
xaxis = list(title = "Log of GDP per Capita (2015 USD)"),
yaxis = list(title = "Trade Dependency (% of GDP)"),
coloraxis = list(
colorscale = list(
c(0, "darkorange"), # High net imports (deficit)
c(0.5, "black"), # Balanced trade
c(1, "darkblue") # High net exports (surplus)
),
colorbar = list(
title = list(text = "Log of Net Export<br>(Exports - Imports)")
)
),
template = "plotly_white"
)
fig
## Warning: Ignoring 66 observations
trade_data_anim <- trade_data %>%
filter(gdp_percap > 0,
!is.na(gdp_percap),
!is.na(trade_dep),
!is.na(export),
!is.na(import)) %>%
mutate(
log_gdp_percap = log(gdp_percap),
net_trade_balance = log(abs(export - import)) * sign(export - import)
)
thailand_data <- trade_data_anim %>% filter(country == "Thailand")
others_data <- trade_data_anim %>% filter(country != "Thailand")
custom_text <- ~paste(
country,year,
"<br>GDP per Capita (2015 USD): ", round(gdp_percap, 2),
"<br>Trade Dependency (%): ", round(trade_dep, 2),
"<br>Net Exports (Billions): ", round((export - import)/10000000, 2)
)
fig <- plot_ly() %>%
add_trace(
data = others_data,
x = ~log_gdp_percap,
y = ~trade_dep,
frame = ~year,
text = custom_text,
type = 'scatter',
mode = 'markers',
marker = list(size = 10, opacity = 0.8, color = "lightgray"),
showlegend = FALSE
) %>%
add_trace(
data = thailand_data,
x = ~log_gdp_percap,
y = ~trade_dep,
frame = ~year,
type = 'scatter',
mode = 'markers+text',
text = custom_text,
textfont = list(
family = "Times",
size = 14
),
textposition = 'top center',
marker = list(
size = 12,
opacity = 1,
showscale = FALSE
),
color = ~net_trade_balance,
showlegend = FALSE
) %>%
layout(
title = list(
text = "\nThailand Trade Dependency and GDP Per Capita, 1960-2023",
x = 0.15,
xanchor = "left",
font = list(
family = "Times",
fontface="bold",
size = 18,
color = "black"
)
),
xaxis = list(
title = list(
text = "Log of GDP per Capita (2015 USD)",
font = list(
family = "Times",
size = 14,
color = "black"
)
),
showgrid = FALSE # Drop x-axis grid lines
),
yaxis = list(
title = list(
text = "Trade Dependency (% of GDP)",
font = list(
family = "Times",
size = 14,
color = "black"
)
),
range = c(0, 500),
showgrid = FALSE # Drop y-axis grid lines
),
coloraxis = list(
colorscale = list(
c(-20, "darkorange"),
c(0, "black"),
c(20, "darkblue")
),
colorbar = list(
title = list(
text = "Log of Net Export<br>(Exports - Imports)",
font = list(
family = "Times",
size = 12,
color = "black"
)
),
font = list(
family = "Times",
size = 12,
color = "black"
)
)
),
template = "plotly_white"
) %>%
animation_opts(
frame = 450,
transition = 0,
redraw = TRUE
) %>%
animation_slider(
currentvalue = list(prefix = "Year: ")
)
years <- sort(unique(thailand_data$year))
annotations_list <- list()
if (!is.null(fig$x$frames)) {
for (i in seq_along(fig$x$frames)) {
frame_year <- fig$x$frames[[i]]$name
if (frame_year %in% names(annotations_list)) {
fig$x$frames[[i]]$layout <- list(annotations = list(annotations_list[[frame_year]]))
}
}
}
fig
df <- trade_data %>%
filter(year %in% c(1960, 2023), !is.na(trade_dep), !is.na(income), income != "Aggregates") %>%
group_by(country) %>%
filter(n() == 2) %>%
ungroup() %>%
arrange(country, year) %>%
mutate(
paired = as.numeric(factor(country)),
year = factor(year),
trade_dep = as.numeric(trade_dep),
income = factor(income, levels = c("High income", "Upper middle income", "Lower middle income", "Low income"))
)
year_colors <- c("1960" = "lightblue", "2023" = "darkblue")
p <- ggplot(df, aes(x = trade_dep, y = fct_reorder(country, trade_dep, .na_rm = TRUE))) +
geom_line(aes(group = paired), color = "lightblue") +
geom_point(aes(color = year), size = 2) +
scale_color_manual(name = "Year", values = year_colors) +
labs(
x = "Trade Dependency (% of GDP)",
y = "Country",
title = "Trade Dependency Change by Income Group (1960 vs. 2023)"
) +
theme_minimal() +
theme(text = element_text(size = 10)) +
facet_wrap(~income, ncol = 1, scales = "free_y")
ggplotly(p, height = 800)
world <- ne_countries(scale = "medium", returnclass = "sf") %>%
filter(admin != "Antarctica")
target_crs <- "+proj=moll"
world_moll <- st_transform(world, crs = target_crs)
world_trade <- world_moll %>%
left_join(trade_data_2023, by = c("iso_a3" = "iso3c"))
world_trade_df <- world_trade %>%
st_drop_geometry()
trade_map <- plot_ly(
data = world_trade_df,
type = "choropleth",
locations = ~iso_a3,
z = ~trade_dep,
text = ~paste(admin, "<br>Trade Dependency:", round(trade_dep, 2), "%"),
colorscale = "Viridis",
colorbar = list(title = "Trade Dependency (%)"), # Add title to color bar
marker = list(line = list(color = "black", width = 0.5))
) %>%
layout(
title = "Trade Dependency by Country (2023)",
geo = list(
projection = list(type = "mollweide"),
showcoastlines = TRUE,
coastlinecolor = "black"
)
)
trade_map
## Warning: Ignoring 86 observations
thailand_trade <- trade_data %>%
arrange(year) %>%
filter(country == "Thailand", year >= 1960, year <= 2023) %>%
select(year, export, import, gdp)
fig <- plot_ly(data = thailand_trade) %>%
add_lines(x = ~year, y = ~export, name = "Exports", line = list(color = "darkblue")) %>%
add_lines(x = ~year, y = ~import, name = "Imports", line = list(color = "darkorange")) %>%
# add_lines(x = ~year, y = ~gdp, name = "GDP", line = list(color = "grey")) %>%
layout(
title = "Thailand’s Export and Import (1960-2023)",
xaxis = list(title = "Year"),
yaxis = list(title = "Trade Value (in USD)"),
legend = list(x = 0.1, y = 0.9),
hovermode = "x unified"
)
fig
thailand_trade <- trade_data %>%
filter(country == "Thailand", year >= 1960, year <= 2023) %>%
select(year, export, import) %>%
arrange(year) %>%
mutate(
net_export = export - import
)
fig <- plot_ly(data = thailand_trade) %>%
add_trace(
x = ~year, y = ~import, name = "Imports", type = "scatter", mode = "none",
fill = "tozeroy", fillcolor = "rgba(255, 140, 0, 0.5)"
) %>%
add_trace(
x = ~year, y = ~export, name = "Exports", type = "scatter", mode = "none",
fill = "tozeroy", fillcolor = "rgba(0, 0, 139, 0.5)"
) %>%
add_trace(
x = ~year, y = ~net_export, name = "Net Exports", type = "scatter", mode = "lines",
line = list(color = "black", width = 2, dash = "solid")
) %>%
layout(
title = "Thailand’s Export, Import & Net Export (1960-2023)",
xaxis = list(
title = "Year",
showgrid = FALSE
),
yaxis = list(
title = "Trade Value (in USD)",
zeroline = TRUE, zerolinecolor = "black",
showgrid = FALSE
),
legend = list(x = 0.1, y = 0.9),
hovermode = "x unified",
shapes = list(
list(
type = "line",
x0 = 1997, x1 = 1997,
y0 = min(thailand_trade$import), y1 = max(thailand_trade$export),
xref = "x", yref = "y",
line = list(color = "black", width = 2, dash = "dot")
)
),
annotations = list(
list(
x = 1997, y = max(thailand_trade$export) * 0.8,
text = "<b>Asian Financial Crisis 1997</b><br>Sharp decline in import",
showarrow = TRUE,
arrowhead = 3,
arrowsize = 1,
ax = 50, ay = -40, # Arrow position
bgcolor = "rgba(255, 255, 255, 1)",
bordercolor = "black", # Box border
font = list(size = 12, color = "black")
)
)
)
fig
thailand_trade <- thailand_trade %>%
arrange(year) %>%
mutate(
export_growth = (export / lag(export) - 1) * 100,
import_growth = (import / lag(import) - 1) * 100
) %>%
filter(!is.na(export_growth) & !is.na(import_growth))
fig <- plot_ly(data = thailand_trade) %>%
add_lines(x = ~year, y = ~export_growth, name = "Export Growth (%)", line = list(color = "darkblue")) %>%
add_lines(x = ~year, y = ~import_growth, name = "Import Growth (%)", line = list(color = "darkorange")) %>%
layout(
title = "Thailand’s Export and Import Growth Rate (1960-2023)",
xaxis = list(title = "Year"),
yaxis = list(title = "Growth Rate (%)"),
legend = list(x = 0.1, y = 0.9),
hovermode = "x unified"
)
fig